#pragma once


#include "BasicObject.h"
#include "emotionalmemory.h"
#include "agentproperties.h"
#include "appraisal.h"
#include "world.h"
#include "role.h"

#include <map>
#include <vector>
#include <string>
#include "goal.h"
#include "planningengine.h"

namespace BAA
{

	//class World;

	class Role;
	typedef std::map< Role*,  Role*, std::less< Role*>>		RoleRoleMap;
	typedef std::map<std::string,  Role*, std::less<std::string>>		StringRoleMap;

	class Agent;
	typedef std::vector< Agent*>											AgentVector;
	typedef std::map< Agent*, Agent*, std::less< Agent*>>		AgentPointerMap;
	typedef std::map< int,  Agent*, std::less<int>>					AgentIDMap;
	typedef std::map<std::string,  Agent*, std::less< std::string>>		AgentNameMap;

	class World;
	class Appraisal;
	class AgentProperties;
	class Goal;
	class PlanningEngine;


	class Agent:public BasicObject
	{
	public:
		Agent(const std::string name);


		~Agent();


		// Creates the class, any objects within it
		virtual void Create();


		// Clears the class of any internal objects
		virtual void Clear();

		
		// sets up all data structures used in the various stages
		
		void Initialize();

		virtual void AddRole( Role * role, AgentPointerMap * roleTargets, float roleImportance);

		int getID() { return mID; }
		void ID(int val) { mID = val; }

		void Update(GameTime timeElapsed);

		AgentProperties * Properties() { return mProperties; }
		void Properties(AgentProperties * val) { mProperties = val; }
		

		World * GetWorld() { return world; }
		void SetWorld(World * val) { world = val; }

		void AddToAppraisedEvents(EmotionalMemory * memory)
		{
			if(memory != NULL)
			{
				mAppraisedEvent.push_back(memory);
			}
		}

		Appraisal * AppraisalProcess() const { return mAppraisalProcess; }
		void AppraisalProcess(Appraisal * val) { mAppraisalProcess = val; }

		PlanningEngine * PlanningEng()  { return mPlanningEngine; }
		void PlanningEng(PlanningEngine * val) { mPlanningEngine = val; }

		Action* CurrentAction() const { return mCurrentAction; }
		void CurrentAction(Action* val) { mCurrentAction = val; }

	protected:

		void UpdateActiveEmotionalMemory(GameTime time);

		Goal* SelectBestGoal();

		int mID;

		AgentProperties  *mProperties;

		Appraisal  *mAppraisalProcess;

		// active emotional memory
		std::vector<EmotionalMemory*> mActiveEmotionalMemory;

		std::vector<EmotionalMemory*> mAppraisedEvent;

		StringRoleMap * mRoleSetMap;

		World * world;

		PlanningEngine * mPlanningEngine;

		Action* mCurrentAction;

		Action* mActionIdle;


	};// end class
}// end namespace